/* combinatorics.cpp
Michael Zahniser, 12/12/09

Function definitions for the combinatorics operators.
*/

#include "Operators.h"

using std::string;


namespace {
	string Sum = "sum";
	static const Do<Sum> sum;

	string Product = "product prod";
	static const Do<Product> product;

	string Arithmetic = "arithmetic arith";
	static const Do<Arithmetic> arithmetic;

	string Geometric = "geometric geo";
	static const Do<Geometric> geometric;
}



template <> void Do<Sum>::operator()(State &state) const
{
	double sum = 0.;
	while(!state.Stack().empty())
		sum += state.Pop();
	state.Push(sum);
}



template <> void Do<Product>::operator()(State &state) const
{
	double product = 1.;
	while(!state.Stack().empty())
		product *= state.Pop();
	state.Push(product);
}



template <> void Do<Arithmetic>::operator()(State &state) const
{
	long long count = state.PopInt();
	double step = state.Pop();
	double value = state.Pop();
	
	if(count > 1000)
		throw string("sequence too long");
	
	for( ; count > 0; --count)
	{
		state.Push(value);
		value += step;
	}
}



template <> void Do<Geometric>::operator()(State &state) const
{
	long long count = state.PopInt();
	double scale = state.Pop();
	double value = state.Pop();
	
	if(count > 1000)
		throw string("sequence too long");
	
	for( ; count > 0; --count)
	{
		state.Push(value);
		value *= scale;
	}
}
